#include "PlaneRenderer.h"

namespace GL
{

    PlaneRenderer::PlaneRenderer(ObjectData &data, unsigned int indexes[], const std::string &shaderSource)
    {
        Awake(data);
        ReadShaderSource(shaderSource);

        CreateVertexBuffer(vertexs);

        const int vertexShader = CreateVertexShader(VertexSource);
        const int fragmentShader = CreateFragmentShader(FragmentSource);

        int program = CreateProgram(vertexShader, fragmentShader);
        // 设置顶点属性指针
        int location = GetAttributeLocation(program, "position");
        //
        CreateIndexesBuffer(indexes);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)0);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(3 * sizeof(float)));
        glEnableVertexAttribArray(1);

        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(6 * sizeof(float)));
        glEnableVertexAttribArray(2);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);

        GL_ERROR("{0}", glGetError());
    }

    PlaneRenderer::~PlaneRenderer()
    {
    }

    void PlaneRenderer::Awake(ObjectData &data)
    {

        float copyVertexs[32] = {
            data.r,
            data.t,
            data.n,
            data.R,
            data.G,
            data.B,
            data.r,
            data.t,
            data.r,
            data.b,
            data.n,
            data.R,
            data.G,
            data.B,
            data.r,
            data.b,
            data.l,
            data.b,
            data.n,
            data.R,
            data.G,
            data.B,
            data.l,
            data.b,
            data.l,
            data.t,
            data.n,
            data.R,
            data.G,
            data.B,
            data.l,
            data.t,
        };
        for (int i = 0; i < 32; i++)
        {
            vertexs[i] = copyVertexs[i];
        }
    }

    void PlaneRenderer::Start()
    {
    }

    void PlaneRenderer::CreateIndexesBuffer(unsigned int indexes[])
    {
        unsigned int EBO;
        glGenBuffers(1, &EBO);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(float), indexes, GL_STATIC_DRAW);
    }

    void PlaneRenderer::CreateVertexBuffer(float vertexs[])
    {

        unsigned int vertexBuffer;

        glGenBuffers(1, &vertexBuffer);
        // 顶点缓冲数组
        //  创建顶点缓冲
        glGenVertexArrays(1, &VertexArray);

        // 绑定顶点缓冲
        glBindVertexArray(VertexArray);

        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        glBufferData(GL_ARRAY_BUFFER, 32 * sizeof(float), vertexs, GL_STATIC_DRAW);
    }
    // Texture

    void PlaneRenderer::SetTexture(std::string ImageUrl)
    {
        if (textureIndex > 15)
        {
            GL_ERROR("the texture is More than 16,please check your code");
            return;
        }
        std::string str = "texture" + std::to_string(textureIndex);
        glGenTextures(1, &texture[textureIndex]);
        glBindTexture(GL_TEXTURE_2D, texture[textureIndex]);
        textureIndex++;
        // 为当前绑定的纹理对象设置环绕、过滤方式
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        // 加载并生成纹理

        GL::ImageData data;

        unsigned char *image = GlLoader::LoadImageByUrl(ImageUrl, data);
        if (image)
        {
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, data.Width, data.Height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
            glGenerateMipmap(GL_TEXTURE_2D);
        }
        else
        {
            GL_ERROR("Failed to load texture");
        }

        GlLoader::free(image);

        useProgram();
        glUniform1i(glGetUniformLocation(Program, str.c_str()), textureIndex - 1);
    }

    void PlaneRenderer::Render()
    {

        for (int i = 0; i < textureIndex; i++)
        {

            glActiveTexture(GL_TEXTURE0 + i);
            glBindTexture(GL_TEXTURE_2D, texture[i]);
        }
        useProgram();
        SetMatrix();
        // glDrawArrays(GL_TRIANGLES, 0, 3);

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    }

}